const UserBo = require("./user-bo");
const {request} = require("../utils/request");
const {getDaysBetweenDates, dateDiffWithNumber, isCurrentDay, diifTime} = require("../utils/date");
const UserRecordMapper = require("../database/mapper/user-record")
const {retry, utf16ToUtf8} = require("../utils/fun");
const {sleep} = require("ee-bin/tools/serve");
const Log = require('ee-core/log');
const ProxyUtils = require("../utils/proxy")

module.exports = class RedPacketBo extends UserBo {

    roleLevel = 80
    registered_at = ""
    user_id = 0
    pwd = ""
    old_fans_pwd = ""
    recharge_money = 0
    taskMap = {}
    lastListIds = [] //上一次列表的数据
    network_delay = 0
    /**
     * @type ProxyUtils
     */
    proxy = null

    init() {
        this.userRecordMapper = new UserRecordMapper()
    }

    setRegisteredAt(at) {
        this.registered_at = at
        return this
    }

    setUserId(id) {
        this.user_id = id
        return this
    }

    setPwd(pwd) {
        this.pwd = pwd
        return this
    }

    setOldFansPwd(pwd) {
        this.old_fans_pwd = pwd
        return this
    }

    setRechargeMoney(money) {
        this.recharge_money = money
        return this
    }

    setSender(sender) {
        this.sender = sender
        return this
    }
    setNetworkDelay(val){
        if(val > 0) {
            this.network_delay = parseInt(val)
        }
        return this
    }
    setProxy(proxy){
        if(proxy instanceof ProxyUtils){
            this.proxy = proxy
        }
    }

    async getList() {
        let params = Object.assign(this.getCommonParams(), {
            status: "1,2,4",
            roleLevel: this.roleLevel
        })
        try {
            let startTime = new Date().getTime()
            let op = {
                url: '/api/api.php/protocol/101012',
                method: 'post',
                responseType: 'json',
                formData: params,
                headers: this.headers
            }
            if(this.proxy){
                await this.proxy.setProxyOptions(op)
            }
            let ret = await request(op)
            if (!ret) {
                this.sender.sendMessage("列表获取失败，请检查网络")
                return []
            }
            if (ret.status !== 200) {
                this.sender.sendMessage("请求失败：" + ret.msg)
                return []
            }
            let endTime = new Date().getTime()
            let diff = endTime - startTime
            let time = 0
            for(let i in ret['data']['time_arr']){
                let val = ret['data']['time_arr'][i].replace("s",'') * 1000000
                time += val
            }
            time = parseInt(time/1000)
            this.sender.sendMessage(this.userName +":更新列表，总耗时" + diff +"毫秒,服务器业务处理耗时"+time+"毫秒，请求往返时间为" +(diff-time)+"毫秒")
            return ret['data']['red_envelop_list']
        } catch (e) {
            this.sender.sendMessage("发生未知错误")
            console.log(e)
            return []
        }
    }

    /**
     * 获取最新的列表
     */
    async getLastList() {
        let maps = {}
        let hasRed = false, isUpdate = false
        let redDict = {
            "24H":"24小时新人",
            "3D":"3天",
            '7D':"7天",
            "0":"老粉"
        }
        let redEnvelopList = await this.getList()
        for (let red of redEnvelopList) {
            let diff = diifTime(red['re_start_time'])
            if(diff < 6000000 && diff > -6000000){
                //前后10分钟内是否有新发过的红包
                isUpdate = true
            }
            if (this.isOver(red)) {
                continue
            }
            let type = this.getType(red)
            if (!this.isNewRed(red)) {
                continue
            }
            if (maps[type]) {
                maps[type].push(red)
            } else {
                maps[type] = [red]
            }
            if(type in redDict){
                this.sender.sendMessage("发现"+redDict[type]+"红包！(" + red['id']+")")
                hasRed = true
            }
        }
        if (Object.keys(maps).length != 0) {
            this.lastListIds = redEnvelopList.map(item => {
                return item['id']
            })
        }
        return {hasRed, isUpdate,maps}
    }


    isNewRed(red) {
        if (this.lastListIds.length == 0) {
            return true
        }
        return !this.lastListIds.includes(red['id'])
    }


    getType(red) {
        for (let cond of red['condition_desc_list']) {
            if (cond['desc'].includes("24小时")) {
                return '24H'
            }
            if (cond['desc'].includes("3天")) {
                return '3D'
            }
            if (cond['desc'].includes("7天")) {
                return '7D'
            }
        }
        return "0"
    }

    // 红包是否领取完
    isOver(red) {
        return red['num'] == red['receive_num']
    }

    async receiveByMps(maps) {
        for (let key in maps) {
            let list = maps[key]
            for (let red of list) {
                if (this.isEnableReceive(key, red)) {
                    await this.receiveTask(red, key)
                }
            }
        }
    }

    /**
     * 红包是否可以领取
     */
    isEnableReceive(key, red) {
        if (key == '24H' && dateDiffWithNumber(this.registered_at, red['re_start_time'], 1)) {
            //24小时内可以领取
            return true
        } else if (key == '3D' && dateDiffWithNumber(this.registered_at, red['re_start_time'], 3)) {
            //3天内可以领取
            return true
        } else if (key == '7D' && dateDiffWithNumber(this.registered_at, red['re_start_time'], 7)) {
            //7天内可以领取
            return true
        } else if (key == '0') {
            //无限制
            return true
        }
        return false
    }

    async isRepeat(red) {
        return await this.userRecordMapper.count({
            user_id: this.user_id
            , red_id: red['id']
        }) > 0
    }

    async receiveTask(red, key) {
        if (red['id'] in this.taskMap) {
            this.sender.sendMessage(this.userName + ":任务重复("+red['id']+")")
            return false
        }
        if (await this.isRepeat(red)) {
            this.sender.sendMessage(this.userName + ":红包已领取("+red['id']+")")
            return false
        }

        this.taskMap[red['id']] = 1;
        if (this.recharge_money == 0) {
            this.sender.sendMessage(this.userName + ":没有充值，不可领取红包")
            return false
        }
        let diff = diifTime(red['re_start_time']) > 0 ? diifTime(red['re_start_time']) : 0

        if (diff > 5000) {
            // 模拟真人，向服务端发送任意请求
            setTimeout(async () => {
                this.sender.sendMessage(this.userName + ":模拟人工操获取红包列表")
                await this.getList()
            }, 0)
        }
        if(this.network_delay){
            diff = Math.max(0, diff-this.network_delay)
        }

        this.sender.sendMessage(this.userName + ":创建红包任务("+red['id']+")"+diff+"毫秒后执行")
        setTimeout(async () => {
            await this.retryReceive(red, key)
        }, diff)
        return true
    }

    async retryReceive(red, key) {
        await retry(async () => {
            let ret = this.receive(red, key)
            if (ret !== true) {
                let s = Math.floor(Math.random() * 100);
                if(!isNaN(parseInt(ret)) ){
                    s = ret
                }
                await sleep(s)
            }
            return ret
        }, 5)
    }

    async receive(red, key) {
        let params = Object.assign(this.getCommonParams(), {
            'redEnvelopId': red['id']
        })
        if (red['need_countersign'] == 1){
            let match = red['blessing_message'].match(/口令\s*(\d+)/);
            if (match) {
                params['countersign'] =  match[1]; // 返回口令后面的数字
            }else if(key == '0' && this.old_fans_pwd){
                params['countersign'] = this.old_fans_pwd
            }else{
                params['countersign'] = this.pwd
            }
        }
        try {
            let op = {
                url: '/api/api.php/protocol/101013',
                method: 'post',
                responseType: 'json',
                formData: params,
                headers: this.headers
            }

            if(this.proxy){
                await this.proxy.setProxyOptions(op)
            }

            let ret = await request(op)

            if (ret['status'] == 200) {
                await this.userRecordMapper.create({
                    user_id: this.user_id,
                    red_id: red['id'],
                    money: ret['data']['receive_money']
                })
                this.sender.sendMessage(this.userName + ":领取成功，金额：" + ret['data']['receive_money'] +"("+red['id']+")",{
                    money: parseFloat(ret['data']['receive_money'])
                })
                return true
            }
            this.sender.sendMessage(this.userName + "("+red['id']+"):"+ ret['msg'])
            if(ret['msg'] == '操作频繁'){
                return 200
            }
            return false
        } catch (e) {
            this.sender.sendMessage(this.userName + "("+red['id']+"):"+ "领取失败，请求报错")
            console.log(e)
        }
        return false
    }
}